package cn.com.bluemoon.daps.sync.feignclient;

import cn.com.bluemoon.daps.api.model.RemoteDapModelFieldRenameRecordService;
import cn.com.bluemoon.daps.api.model.RemoteDataModelService;
import cn.com.bluemoon.daps.api.model.RemoteDataModelTableService;
import cn.com.bluemoon.daps.api.model.RemoteModelGroupService;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.model.dto.ModelInfos;
import cn.com.bluemoon.daps.model.entity.*;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.util.function.Tuple4;
import reactor.util.function.Tuples;

import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Jarod.Kong
 */
@Service
@Slf4j
public class DapModelModuleFacade {
    @Autowired
    private RemoteDataModelService modelService;

    @Autowired
    private RemoteModelGroupService groupService;

    @Autowired
    private RemoteDataModelTableService tableService;

    @Autowired
    private RemoteDapModelFieldRenameRecordService fieldRenameRecordService;

    /**
     * 获取表字段变化信息
     */
    public List<ModelFieldRename> listTableFieldRenames(String tableId, String fieldId) {
        ResultBean<List<DapDataModelFieldRenameRecord>> res = fieldRenameRecordService.renameRecordList(tableId, fieldId);
        return res.convert(list -> list.stream().map(ModelFieldRename::new)
                .collect(Collectors.toList())).getContent();
    }

    /**
     * 删除表字段变化信息
     */
    public void delTableRenames(String tableId, @Nullable String fieldId) {
        try {
            ResultBean<String> res = fieldRenameRecordService.deleteRecord(tableId, fieldId);
            log.info("清除表字段变化信息：tableId={},fieldId={}, status={}",tableId, fieldId, res);
        } catch (Exception e) {
            log.error("调用模型服务失败", e);
        }
    }

    public DapDataModel getByIdAsset(String modelId, String errorMsg) {
        ResultBean<DapDataModel> modelR = modelService.getById(modelId);
        DapDataModel model = modelR.getContent();
        BmAssetUtils.isTrue((modelR.isOk() && model != null), errorMsg != null ? errorMsg : modelR.getMsg());
        return model;
    }

    public List<DapDataModelGroup> initModelDefaultGroup(String modelId) {
        ResultBean<List<DapDataModelGroup>> res = groupService.modelGroups(modelId);
        BmAssetUtils.isTrue(res.isOk(), res.getMsg());
        return res.getContent();
    }

    /**
     * @param tableIds null 获取所有表 ！null获取指定表
     */
    public Tuple4<List<DapDataModelTable>,
            List<DapDataModelTableField>,
            List<DapDataModelSubordinateKey>,
            List<DapDataModelTablePartition>> queryModelInfosByModelAndNewestAndTableIds(String modelId, Boolean newest, @Nullable List<String> tableIds) {
        if (newest == null) {
            newest = Boolean.TRUE;
        }
        // 保持与历史版本行为一直 null或空都获取全部表
        if (tableIds != null && tableIds.isEmpty()) {
            tableIds = null;
        }
        ResultBean<ModelInfos> res = modelService.queryModelInfosByModelAndNewestAndTableIds(modelId, newest, tableIds);
        BmAssetUtils.isTrue(res.isOk(), res.getMsg());
        ModelInfos infos = res.getContent();
        return Tuples.of(infos.getTables(), infos.getFields(), infos.getIndexes(), infos.getPartitions());
    }

    /**
     * 获取模型的表信息s
     *
     * @param modelId mid
     * @param newest  newst
     * @return list
     */
    public List<DapDataModelTable> queryModelTables(String modelId, boolean newest) {
        ResultBean<List<DapDataModelTable>> tbsR = tableService.listByModelIdAndNewest(modelId, newest);
        BmAssetUtils.isTrue(tbsR.isOk(), tbsR.getMsg());
        List<DapDataModelTable> tbs = tbsR.getContent();
        return tbs;
    }

    /**
     * 根据模型id+表id获取表信息
     *
     * @param modelId  mid
     * @param newest   newst
     * @param tableIds 指定表id信息 null则返回模型下的全部表
     * @return list
     */
    public List<DapDataModelTable> queryModelTablesByTableIds(String modelId, boolean newest, List<String> tableIds) {
        List<DapDataModelTable> dapDataModelTables = queryModelTables(modelId, newest);
        if (tableIds == null) {
            return dapDataModelTables;
        }
        HashSet<String> tbIds = new HashSet<>(tableIds);
        return dapDataModelTables.stream().filter(d -> tbIds.contains(d.getId())).collect(Collectors.toList());
    }

    public List<DapDataModelTable> queryModelTablesByTableNames(String modelId, boolean newest, List<String> tableNames) {
        List<DapDataModelTable> dapDataModelTables = queryModelTables(modelId, newest);
        if (tableNames == null) {
            return dapDataModelTables;
        }
        HashSet<String> tbNames = new HashSet<>(tableNames);
        return dapDataModelTables.stream().filter(d -> tbNames.contains(d.getEngName())).collect(Collectors.toList());
    }

    /**
     * 模型id
     * name
     */
    public List<ModelInfo> queryAllModels() {
        // 获取所有模型
        ResultBean<List<DapDataModel>> res = modelService.findAllOrFindLikeName("");
        List<DapDataModel> models = res.assetTrue();
        return models.stream().map(v -> new ModelInfo(v.getId(), v.getName())).collect(Collectors.toList());
    }

    @RequiredArgsConstructor
    @Data
    public static class ModelInfo{
        private final String modelId;
        private final String modelName;

    }

    /**
     * 修改表数据
     * 用于解决表加星问题
     *
     * @param modelId m
     * @param tableId t
     */
    public void updateTableUpdateTime(String modelId, String tableId) {
        ResultBean<Boolean> updateTime = tableService.updateTableTime(modelId, tableId);
        log.info("更新表id={}, modelId={}：{}", tableId, modelId, updateTime);
    }

    public static class ModelFieldRename {
        private String modelId;

        private String tableId;

        private String fieldId;

        private String newFieldName;

        private String oldFieldName;

        public ModelFieldRename(DapDataModelFieldRenameRecord record) {
            BeanUtils.copyProperties(record, this);
        }
    }
}
